#pragma once

namespace zzz{
template<typename TI, typename TO> //TI for input type, TO for output type
class Function
{
public:
  typedef TI InputType;
  typedef TO OutputType;

  const TI InputMin;
  const TI InputMax;

  Function(const TI imin, const TI imax)
    :InputMin(imin),InputMax(imax) {}

  virtual bool CheckInput(const TI& x)  //this function could be overload to check the input parameter
  {
    return Within<TI>(InputMin, x,InputMax);
  }

  TO operator()(const TI &x)
  {
    ZCHECK(CheckInput(x))<<"input out of range";
    return Evaluate(x);
  }

  virtual TO Evaluate(const TI& x)=0;  //every derived class need to implement this function
};
}
